﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Labthink.PCSoft.UniversalHost4.DataAccess;
using Labthink.PCSoft.UniversalHost4.Model;
using Labthink.PCSoft.UniversalHost4.Model.User;
using Labthink.PCSoft.UniversalHost4.Utility;
using Newtonsoft.Json;
using NLog;
using Report.Model;
using SystemSettings;
using FullData = Labthink.PCSoft.UniversalHost4.Model.FullData;

namespace Report
{
    public class ReportManager2
    {
        private readonly DataSet _ds;//报表数据源
        private DataSet _source;
        private readonly List<string> _files;//数据库文件
        private readonly Dictionary<string, string> _languages;
        private Dictionary<int, ReportConfig> _cfgs;
        public Dictionary<int, string> AddInputs;
        public List<Curve> Curves { get; private set; }
        public List<FullData> ParamInfo { get; private set; }

        public List<FullData> ParamInfoOrigin { get; private set; }

        public List<FullData> DataInfo { get; private set; }
        public List<FullData> ResultInfo { get; private set; }
        public List<SelectedData> ParamSelected { get; private set; }
        public List<SelectedData> DataSelected { get; private set; }
        public List<SelectedData> ResultSelected { get; private set; }

        private readonly ReportInfo _ri;

        private static ReportManager2 _manager;

        public List<UserPermission> Permissions { get; set; }
        public UserInfo User { get; set; }
        public int TypeId { get; set; }
        private int _type;
        public int Id { get; private set; }

        private Logger Logger = LogManager.GetCurrentClassLogger();

        private ReportManager2()
        {
            _languages = new Dictionary<string, string>();
            _ds = new DataSet();
            _files = new List<string>();
            Curves = new List<Curve>();
            ResultInfo = new List<FullData>();
            DataInfo = new List<FullData>();
            ParamInfo = new List<FullData>();
            ParamSelected = new List<SelectedData>();
            DataSelected = new List<SelectedData>();
            ResultSelected = new List<SelectedData>();
            _cfgs = new Dictionary<int, ReportConfig>();
            AddInputs = new Dictionary<int, string>();
            TypeId = 10033;
            _ri = new ReportInfo
            {
                Title = ReportCommon.GetLan.GetLanguageValue("TestReport"),
                Sign = "",
                UserInfo = "",
                Param = ReportCommon.GetLan.GetLanguageValue("TestParam"),
                Result = ReportCommon.GetLan.GetLanguageValue("TestResult"),
                DataCurve = ReportCommon.GetLan.GetLanguageValue("TestCurve"),
                DateList = ReportCommon.GetLan.GetLanguageValue("DataList"),
                ResultCurve = "",
                ResultList = ""
            };
        }

        public static ReportManager2 Create()
        {
            return _manager ??= new ReportManager2();
        }

        public void GetConfigs(List<ReportConfig> cfgs)
        {
            _cfgs = new Dictionary<int, ReportConfig>();
            foreach (var cfg in cfgs.Where(c => c.Type > 0))
            {
                _cfgs.Add(cfg.Type, cfg);
            }
        }

        public int SaveConfigAsync()
        {
            var cfg = new ReportConfig
            {
                Type = _type,
                Param = JsonConvert.SerializeObject(ParamSelected),
                Result = JsonConvert.SerializeObject(ResultSelected),
                DataList = JsonConvert.SerializeObject(DataSelected),
                DataCurve = JsonConvert.SerializeObject(Curves),
                ResultCurve = ""
            };

            var r = ReportConfigManager.UpdateConfig(cfg);
            if (r >= 0)
            {
                if (_cfgs.ContainsKey(_type))
                {
                    _cfgs[_type] = cfg;
                }
                else
                {
                    _cfgs.Add(_type, cfg);
                }

                AddInputs.Clear();
                foreach (var ps in ParamSelected.Where(p => !string.IsNullOrEmpty(p.Text)))
                {
                    //if (ParamInfo.All(d => d.DataNo != ps.Id))
                    {
                        AddInputs.Add(ps.Id, "");
                    }
                }

                //foreach (var ps in ResultSelected.Where(p => !string.IsNullOrEmpty(p.Text)))
                //{
                //    if (ResultInfo.All(d => d.DataNo != ps.Id))
                //    {
                //        AddInputs.Add(ps.Id, "");
                //    }
                //}

                LogAsync(ReportCommon.GetLan.GetLanguageValue("ReportLogSaveConfig"));
            }

            return r;
        }

        public void LogAsync(string log)
        {
            LogRepository.AddLog(log, "REPORT");
        }

        public int AddCurves(string title, bool isDrawPoint, Axis x, params Axis[] ys)
        {
            if (Curves.Any(d => d.Title == title)) return -1;
            var c = new Curve
            {
                X = x,
                Y = new List<Axis>(ys),
                Title = title,
                IsDrawPoint = isDrawPoint
            };

            var str = new StringBuilder();
            foreach (var y in ys)
            {
                str.Append(DataInfo.Single(d => d.DataNo == y.Id).Text).Append(",");
            }

            Curves.Add(c);
            LogAsync(string.Format(ReportCommon.GetLan.GetLanguageValue("ReportLogAddCurve"), title, DataInfo.Single(d => d.DataNo == x.Id).Text, str.Remove(str.Length - 1, 1)));
            return 0;
        }

        public void AddFile(string file)
        {
            Logger.Debug($"Open report with file {file}");
            _files.Add(file);
            _initInfo();
        }

        public void AddInfo(string sign, string user)
        {
            _ri.Sign = sign;
            _ri.UserInfo = user;
        }

        public void Clear()
        {
            _files.Clear();
            _source = null;
            //ResultInfo.Clear();
            //DataInfo.Clear();
            //ParamInfo.Clear();
            //Curves.Clear();
        }

        public DataSet CreateReportData()
        {
            _ds.Clear();
            _ds.Tables.Clear();
            if (_source == null)
            {
                var sda = new SqliteDataAccess(_files[0]);
                _source = sda.GetAllData();
            }

            _createInfo();
            _createParam(_source);
            _createResult(_source);
            _createDataCurve(_source);
            //_createDataList(_source);
            return _ds;
        }

        public void AddParam(string name, string value)
        {
            var max1 = ParamSelected.Max(p => p.Id);
            var max2 = ParamInfo.Max(p => p.DataNo);
            var id = Math.Max(max1, max2) + 1;
            ParamSelected.Add(new SelectedData { Id = id, Text = name });
            ParamInfo.Add(new FullData
            {
                DataNo = id,
                Text = name,
                Value = value,
                ColumnName = ""
            });

            LogAsync(string.Format(ReportCommon.GetLan.GetLanguageValue("ReportLogAddParam"), name, value));
        }

        public void RemoveParams(List<int> removes)
        {
            if (removes == null)
            {
                _resetParam1();
                LogAsync(ReportCommon.GetLan.GetLanguageValue("ReportLogResetParam"));
                return;
            }

            ParamSelected.Clear();
            foreach (var fd in ParamInfo)
            {
                ParamSelected.Add(new SelectedData { Id = fd.DataNo });
            }

            foreach (var remove in removes)
            {
                var p = ParamSelected.SingleOrDefault(ps => ps.Id == remove);
                if (p != null)
                {
                    ParamSelected.Remove(p);
                    LogAsync(string.Format(ReportCommon.GetLan.GetLanguageValue("ReportLogRemoveParam"), ParamInfo.Single(d => d.DataNo == remove).Text));
                }
            }
        }

        private void _resetParam1()
        {
            ParamSelected.Clear();
            ParamInfo.RemoveAll(d => string.IsNullOrEmpty(d.ColumnName));
            foreach (var fd in ParamInfo)
            {
                ParamSelected.Add(new SelectedData { Id = fd.DataNo });
            }
        }

        public void SequenceParams(List<SelectedData> seqs)
        {
            if (seqs == null)
            {
                _resetParam2();
                return;
            }

            foreach (var seq in seqs)
            {
                var p = ParamSelected.SingleOrDefault(ps => ps.Id == seq.Id);
                if (p != null) p.Sequence = seq.Sequence;
            }
        }

        private void _resetParam2()
        {
            foreach (var fd in ParamSelected)
            {
                fd.Sequence = 0;
            }
        }

        public void AddResult(string name, string value)
        {
            var max1 = ResultSelected.Max(p => p.Id);
            var max2 = ResultInfo.Max(p => p.DataNo);
            var id = Math.Max(max1, max2) + 1;
            ResultSelected.Add(new SelectedData { Id = id, Text = name });
            ResultInfo.Add(new FullData
            {
                DataNo = id,
                Text = name,
                Value = value,
                ColumnName = ""
            });

            LogAsync(string.Format(ReportCommon.GetLan.GetLanguageValue("ReportLogAddResult"), name, value));
        }

        public void RemoveResults(List<int> removes)
        {
            if (removes == null)
            {
                _resetResult1();
                LogAsync(ReportCommon.GetLan.GetLanguageValue("ReportLogResetResult"));
                return;
            }

            foreach (var remove in removes)
            {
                var p = ResultSelected.SingleOrDefault(ps => ps.Id == remove);
                if (p != null)
                {
                    ResultSelected.Remove(p);
                    LogAsync(string.Format(ReportCommon.GetLan.GetLanguageValue("ReportLogRemoveResult"), ResultInfo.Single(d => d.DataNo == remove).Text));
                }
            }
        }

        private void _resetResult1()
        {
            ResultSelected.Clear();
            ResultInfo.RemoveAll(d => string.IsNullOrEmpty(d.ColumnName));
            foreach (var fd in ResultInfo)
            {
                ResultSelected.Add(new SelectedData { Id = fd.DataNo });
            }
        }

        public void SequenceResults(List<SelectedData> seqs)
        {
            if (seqs == null)
            {
                _resetResult2();
                return;
            }
            foreach (var seq in seqs)
            {
                var p = ResultSelected.SingleOrDefault(ps => ps.Id == seq.Id);
                if (p != null) p.Sequence = seq.Sequence;
            }
        }

        public void PrecisionResults(List<SelectedData> seqs)
        {
            if (seqs == null)
            {
                _resetResult3();
                return;
            }
            foreach (var seq in seqs)
            {
                if (seq.Precision.HasValue)
                {
                    var p = ResultSelected.SingleOrDefault(ps => ps.Id == seq.Id);
                    if (p != null) p.Precision = seq.Precision;
                }
            }
        }

        private void _resetResult2()
        {
            foreach (var fd in ResultSelected)
            {
                fd.Sequence = 0;
            }
        }

        private void _resetResult3()
        {
            var sda = new SqliteDataAccess(_files.Last());
            foreach (var fd in ResultSelected)
            {
                fd.Precision = null;
            }
        }

        public int RemoveCurve(string title)
        {
            var curve = Curves.SingleOrDefault(c => c.Title == title);
            if (curve == null) return -1;
            var r = Curves.Remove(curve) ? 1 : -1;
            if (r > 0)
                LogAsync(string.Format(ReportCommon.GetLan.GetLanguageValue("ReportLogRemoveCurve"), title));
            return r;
        }

        public void SetDataList(List<SelectedData> sds)
        {

            DataSelected.Clear();
            if (sds != null) DataSelected.AddRange(sds);
        }

        public void SetResultList(List<SelectedData> sds)
        {
            ResultSelected.Clear();
            if (sds != null) ResultSelected.AddRange(sds);
        }

        private void _createInfo()
        {
            var dt = _ds.Tables.Add("RI");
            var t = typeof(ReportInfo);
            foreach (var pi in t.GetProperties())
            {
                dt.Columns.Add(pi.Name, pi.PropertyType);
            }

            var dr = dt.NewRow();
            foreach (var pi in t.GetProperties())
            {
                dr[pi.Name] = pi.GetValue(_ri, null);
            }

            dt.Rows.Add(dr);
        }

        private void _createParam(DataSet ds)
        {
            //参数
            var dt = _ds.Tables.Add("PT");
            var t = typeof(ParamTable);
            foreach (var pi in t.GetProperties())
            {
                dt.Columns.Add(pi.Name, pi.PropertyType);
            }

            var tmpParam = ParamInfo;
            if (ParamSelected.Count > 0)
            {
                //如果有用户选择的参数
                tmpParam = new List<FullData>();
                foreach (var ps in ParamSelected.OrderBy(p => p.Sequence))
                {
                    var pi = ParamInfo.SingleOrDefault(d => d.DataNo == ps.Id);
                    if (pi != null) tmpParam.Add(pi);
                    else tmpParam.Add(new FullData
                    {
                        DataNo = ps.Id,
                        Text = ps.Text,
                        Value = AddInputs[ps.Id],
                        ColumnName = ""
                    });
                }
            }

            //生成数据
            var index = 0;
            var dr = dt.NewRow();
            var param = ds.Tables[0];
            foreach (var tp in tmpParam)
            {
                var name = tp.Text;
                var value = tp.Value?.ToString() ?? "";

                if (param.Columns.Contains(tp.ColumnName))
                {
                    value = param.Rows[0][tp.ColumnName].ToString();
                    //数据库原值
                    if (tp.DataType != DataType.String)
                    {
                        if ((int)value.ToDouble() == -1) value = "--";
                        else if (tp.DataType == DataType.Int)
                        {
                            if (_languages.ContainsKey(tp.LanguageId + value))
                                value = _languages[tp.LanguageId + value];
                        }
                        else if (tp.DataType == DataType.Double)
                        {
                            value = _round(value.ToDouble(), tp.Precision);
                        }
                        else if (tp.DataType == DataType.EDouble)
                        {
                            value = value.ScientificNotation(tp.Precision) + "";
                        }
                    }

                    if (value == "-1") value = "--";
                    else
                    {
                        if (!string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(tp.Unit) && value != "--" && tp.Unit != "null")
                        {
                            value += "(" + tp.Unit + ")";
                        }
                    }
                }

                if (index % 2 == 0)
                {
                    dr["ParamName1"] = name;
                    dr["ParamValue1"] = value;
                }
                else
                {
                    dr["ParamName2"] = name;
                    dr["ParamValue2"] = value;
                    dt.Rows.Add(dr);
                    dr = dt.NewRow();
                }

                index++;
            }

            if (index % 2 != 0)
            {
                dt.Rows.Add(dr);
            }
        }

        /// <summary>
        /// 结果
        /// </summary>
        /// <param name="ds"></param>
        private void _createResult(DataSet ds)
        {
            double rate = 0.0;
            int okCount = 0;
            int badCount = 0;
            var dt = _ds.Tables.Add("RL");
            var t = typeof(DataList);
            foreach (var pi in t.GetProperties())
            {
                dt.Columns.Add(pi.Name, pi.PropertyType);
            }

            var dn = _ds.Tables.Add("RN");
            t = typeof(DataListName);
            foreach (var pi in t.GetProperties())
            {
                dn.Columns.Add(pi.Name, pi.PropertyType);
            }

            //如果有用户选择的结果
            var tmpParam = new List<FullData>();
            foreach (var ps in ResultSelected.OrderBy(p => p.Sequence))
            {
                tmpParam.Add(ResultInfo.Single(d => d.DataNo == ps.Id));
            }

            var param = ds.Tables[2];
            int index;
            var rowNo = 1;
            foreach (DataRow dr in param.Rows)
            {
                index = 1;
                var row = dt.NewRow();
                row["Data"] = rowNo;
                foreach (var fd in tmpParam)
                {
                    if (index > 8) break;

                    if (fd.DataType == DataType.Int)
                    {
                        row["Data" + index] = dr[fd.ColumnName];
                        if (dr[fd.ColumnName].ToInt() < 0)
                        {
                            row["Data" + index] = "--";
                        }

                        if (_languages.ContainsKey(fd.LanguageId + dr[fd.ColumnName]))
                        {
                            row["Data" + index] = _languages[fd.LanguageId + dr[fd.ColumnName]];
                        }

                        if (dr[fd.ColumnName].ToInt() == 1) // 合格
                        {
                            okCount++;
                        }
                        else
                        {
                            badCount++; // 661： 0：不合格，2：无效
                        }
                    }
                    else if (fd.DataType == DataType.Double)
                    {
                        var d = dr[fd.ColumnName].ToDouble();
                        var v = _round(d, fd.Precision);
                        row["Data" + index] = d == -1 ? "--" : v;
                    }
                    else if (fd.DataType == DataType.EDouble)
                    {
                        row["Data" + index] = dr[fd.ColumnName].ToDouble().ScientificNotation(fd.Precision);
                    }
                    else if (fd.DataType == DataType.DateTime)
                    {
                        row["Data" + index] = Convert.ToDateTime(dr[fd.ColumnName]).ToString("MM-dd HH:mm:ss");
                    }
                    else
                    {
                        row["Data" + index] = dr[fd.ColumnName].ToString();
                    }

                    index++;
                }

                dt.Rows.Add(row);
                rowNo++;
            }

            var total = okCount + badCount;
            if (total == 0)
            {
                rate = -1;
            }
            else
            {
                rate = Math.Round(okCount / (total * 1.0), 4) * 100;
            }

            // 统计
            if (ResultSelected.Any())
            {
                foreach (var rr in ResultSelected)
                {
                    rr.Text ??= "";
                }

                foreach (var str in ResultSelected.First().Text.Split(','))
                {
                    if (string.IsNullOrEmpty(str))
                    {
                        continue;
                    }

                    var row = dt.NewRow();
                    index = 1;
                    row["Data"] = ReportCommon.GetLan.GetLanguageValue("Value" + str);
                    foreach (var fd in tmpParam)
                    {
                        if (fd.DataNo == 10040)
                        {
                            row["Data" + index] = "--";
                            index++;
                            continue;
                        }

                        if (index > 8) break;
                        var obj = param.Compute(str + "(" + fd.ColumnName + ")", fd.ColumnName + ">-1");
                        if (string.IsNullOrEmpty(obj.ToString()))
                        {
                            row["Data" + index] = "--";
                            index++;
                            continue;
                        }

                        if (fd.DataType == DataType.Int)
                        {
                            row["Data" + index] = _round(obj.ToDouble(), 1);
                        }
                        else if (fd.DataType == DataType.Double)
                        {
                            row["Data" + index] = _round(obj.ToDouble(), fd.Precision + 1);
                        }
                        else if (fd.DataType == DataType.EDouble)
                        {
                            row["Data" + index] = obj.ScientificNotationStr(fd.Precision + 1);
                        }
                        else if (fd.DataType == DataType.DateTime)
                        {
                            row["Data" + index] = "--";
                        }
                        else
                        {
                            row["Data" + index] = "--";
                        }

                        index++;
                    }

                    dt.Rows.Add(row);
                }

            }

            index = 1;
            var r = dn.NewRow();
            r["Dln"] = "No.";
            foreach (var fd in tmpParam)
            {
                if (index > 8) break;
                var str = fd.Text;
                if (!string.IsNullOrEmpty(fd.Unit) && fd.Unit != "null")
                {
                    str += "(" + fd.Unit + ")";
                }

                r["Dln" + index] = str;
                index++;
            }

            dn.Rows.Add(r);
        }

        private void _createDataCurve(DataSet ds)
        {
            var dt = _ds.Tables.Add("CI");
            var param = ds.Tables[1];
            if (param.Rows.Count == 0) return;
            var t = typeof(CurveInfo);
            foreach (var pi in t.GetProperties())
            {
                dt.Columns.Add(pi.Name, pi.PropertyType);
            }

            ImageFactory.Clear();
            var index = 1;
            foreach (var curve in Curves)
            {
                var file = ImageFactory.GetReportImage(curve, DataInfo, param);
                var dr = dt.NewRow();

                dr["CurveName"] = string.IsNullOrEmpty(curve.Title) ? string.Format(ReportCommon.GetLan.GetLanguageValue("CurveNameSeq"), index) : curve.Title;
                dr["CurveFile"] = "file:///" + file;
                dt.Rows.Add(dr);
                index++;
            }
        }

        private void _createDataList(DataSet ds)
        {
            var dt = _ds.Tables.Add("DL");
            var t = typeof(DataList);
            foreach (var pi in t.GetProperties())
            {
                dt.Columns.Add(pi.Name, pi.PropertyType);
            }

            var dn = _ds.Tables.Add("DN");
            t = typeof(DataListName);
            foreach (var pi in t.GetProperties())
            {
                dn.Columns.Add(pi.Name, pi.PropertyType);
            }

            if (DataSelected.Count == 0) return;

            //如果有用户选择的参数
            var tmpParam = new List<FullData>();
            foreach (var ps in DataSelected.OrderBy(p => p.Sequence))
            {
                tmpParam.Add(DataInfo.Single(d => d.DataNo == ps.Id));
            }

            var param = ds.Tables[1];
            int index;
            foreach (DataRow dr in param.Rows)
            {
                index = 1;
                var row = dt.NewRow();
                foreach (var fd in tmpParam)
                {
                    if (index > 8) break;

                    if (fd.DataType == DataType.Int)
                    {
                        row["Data" + index] = dr[fd.ColumnName];
                    }
                    else if (fd.DataType == DataType.Double)
                    {
                        row["Data" + index] = _round(dr[fd.ColumnName].ToDouble(), fd.Precision);
                    }
                    else if (fd.DataType == DataType.EDouble)
                    {
                        row["Data" + index] = dr[fd.ColumnName].ToDouble().ScientificNotation(fd.Precision);
                    }
                    else if (fd.DataType == DataType.DateTime)
                    {
                        row["Data" + index] = Convert.ToDateTime(dr[fd.ColumnName]).ToString("MM-dd HH:mm:ss.fff");
                    }
                    else
                    {
                        row["Data" + index] = dr[fd.ColumnName].ToString();
                    }

                    index++;
                }

                dt.Rows.Add(row);
            }

            index = 1;
            var r = dn.NewRow();
            r["Dln"] = "No.";
            foreach (var fd in tmpParam)
            {
                if (index > 8) break;
                var str = fd.Text;
                if (!string.IsNullOrEmpty(fd.Unit) && fd.Unit != "null")
                {
                    str += "(" + fd.Unit + ")";
                }

                r["Dln" + index] = str;
                index++;
            }
            dn.Rows.Add(r);
        }

        private void _initInfo()
        {
            var sda = new SqliteDataAccess(_files.Last());
            if (_languages.Count == 0)
            {
                var lans = sda.GetLanguages();
                foreach (var l in lans)
                {
                    _languages.Add(l.LanguageId, l.Text);
                }
            }

            Id = sda.GetTestId();
            ParamInfo = sda.GetParameters();
            var name = ParamInfo.Single(d => d.DataNo == TypeId).ColumnName;
            var tmp = sda.GetOneParamValue(name).ToInt();

            if (tmp != _type)
            {
                AddInputs.Clear();
                var pi = ParamInfo.SingleOrDefault(p => p.DataNo == 10034);
                if (pi != null) ParamInfo.Remove(pi);
                ResultInfo = sda.GetResults();
                pi = ResultInfo.SingleOrDefault(p => p.DataNo == 10034);
                if (pi != null) ResultInfo.Remove(pi);
                DataInfo = sda.GetData();
                DataSelected.Clear();
                _type = tmp;
                if (_cfgs.ContainsKey(_type))
                {
                    var cfg = _cfgs[_type];
                    if (!string.IsNullOrEmpty(cfg.Param))
                    {
                        ParamSelected = JsonConvert.DeserializeObject<List<SelectedData>>(cfg.Param);
                        if (ParamSelected.Count == 0)
                        {

                        }
                    }
                    else
                    {
                        ParamSelected.Clear();
                        foreach (var fd in ParamInfo)
                        {
                            if (fd.DataNo == 10034 || fd.DataNo == 10033)
                                continue;

                            ParamSelected.Add(new SelectedData { Id = fd.DataNo });
                        }
                    }

                    if (!string.IsNullOrEmpty(cfg.Result))
                    {
                        ResultSelected = JsonConvert.DeserializeObject<List<SelectedData>>(cfg.Result);
                        foreach (var r in ResultSelected)
                        {
                            r.Text ??= "";
                        }

                        if (ResultSelected.Count == 0)
                        {
                            foreach (var fd in ResultInfo)
                            {
                                if (fd.DataNo == 10034) continue;
                                ResultSelected.Add(new SelectedData { Id = fd.DataNo });
                            }
                        }
                    }

                    if (!string.IsNullOrEmpty(cfg.DataList))
                    {
                        DataSelected = JsonConvert.DeserializeObject<List<SelectedData>>(cfg.DataList);
                    }

                    if (!string.IsNullOrEmpty(cfg.DataCurve))
                    {
                        Curves = JsonConvert.DeserializeObject<List<Curve>>(cfg.DataCurve);
                    }

                    foreach (var ps in ParamSelected)
                    {
                        if (ParamInfo.All(d => d.DataNo != ps.Id))
                        {
                            AddInputs.Add(ps.Id, "");
                            ParamInfo.Add(new FullData
                            {
                                DataNo = ps.Id,
                                Text = ps.Text,
                                Value = "",
                                ColumnName = ""
                            });
                        }
                    }

                    //foreach (var ps in ResultSelected)
                    //{
                    //    if (ResultInfo.All(d => d.DataNo != ps.Id))
                    //    {
                    //        AddInputs.Add(ps.Id, "");
                    //        ResultInfo.Add(new FullData
                    //        {
                    //            DataNo = ps.Id,
                    //            Text = ps.Text,
                    //            Value = "",
                    //            ColumnName = ""
                    //        });
                    //    }
                    //}
                }
                else
                {
                    ParamSelected.Clear();
                    foreach (var fd in ParamInfo)
                    {
                        ParamSelected.Add(new SelectedData { Id = fd.DataNo });
                    }

                    ResultSelected.Clear();
                    foreach (var fd in ResultInfo)
                    {
                        if (fd.DataNo == 10034) continue;
                        ResultSelected.Add(new SelectedData { Id = fd.DataNo });
                    }
                }
            }
            //else
            //{
            //    foreach (var ps in ParamSelected)
            //    {
            //        if (ParamInfo.All(d => d.DataNo != ps.Id))
            //        {
            //            //AddInputs.Add(ps.Id, "");
            //            ParamInfo.Add(new FullData
            //            {
            //                DataNo = ps.Id,
            //                Text = ps.Text,
            //                Value = "",
            //                ColumnName = ""
            //            });
            //        }
            //    }
            //}

            if (_cfgs.ContainsKey(_type))
            {
                var cfg = _cfgs[_type];
                if (!string.IsNullOrEmpty(cfg.DataCurve))
                {
                    Curves = JsonConvert.DeserializeObject<List<Curve>>(cfg.DataCurve);
                }
            }
        }

        private string _round(double d, int p)
        {
            string format = "0";
            if (p > 0)
            {
                for (int j = 0; j < p; j++)
                {
                    format += "0";
                }
                format = format.Insert(1, ".");
            }

            //return Math.Round(value, digits).ToString();
            return d.ToString(format);
        }

        public Stream CreateReportStream(string path)
        {
            var s = new MemoryStream();
            var xml = XDocument.Load(path);
            if (ResultSelected.Count > 0)
            {
                // 添加数据列表标题
                // 找到ReportItems节点
                var report = xml.FirstNode as XContainer;
                var items = report?.Nodes().ToArray()[3] as XElement;
                var reportSection = items?.FirstNode as XContainer;
                var body = reportSection?.FirstNode as XContainer;
                if (body?.FirstNode is XContainer reportItems)
                {
                    var node = reportItems.Elements()
                        .SingleOrDefault(p =>
                        {
                            var xAttribute = p.Attribute("Name");
                            return xAttribute != null && xAttribute.Value == "TxtResultTitle";
                        });

                    node?.AddAfterSelf(XElement.Parse(_getResultListTable()));

                    //var ln = reportItems.LastNode;
                    //ln.AddAfterSelf(XElement.Parse(_getDataListName()));

                    //ln = reportItems.LastNode;
                    //ln.AddAfterSelf(XElement.Parse(_getDataListTable()));
                }
            }

            xml.Save(s);
            s.Position = 0;
            return s;
        }

        private string _getDataListName()
        {
            var xml = new StringBuilder("<Textbox  xmlns=\"http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition\"");
            xml.Append(" xmlns:rd=\"http://schemas.microsoft.com/SQLServer/reporting/reportdesigner\" Name = \"TxtDataListName\">");
            xml.Append("<CanGrow>true</CanGrow>");
            xml.Append("<KeepTogether>true</KeepTogether>");
            xml.Append("<Paragraphs><Paragraph><TextRuns><TextRun>");
            xml.Append("<Value>= First(Fields!DateList.Value, \"RI\")</Value>");
            xml.Append("<Style>");
            xml.Append("<FontFamily>宋体</FontFamily>");
            xml.Append("</Style>");
            xml.Append("</TextRun></TextRuns><Style/></Paragraph></Paragraphs>");
            xml.Append("<rd:DefaultName>Textbox10</rd:DefaultName>");
            xml.Append("<Top>16.81433cm</Top>");
            xml.Append("<Left>0.11305cm</Left>");
            xml.Append("<Height>0.6cm</Height>");
            xml.Append("<Width>5.38396cm</Width>");
            xml.Append("<ZIndex>6</ZIndex>");
            xml.Append("<Style><Border><Style>None</Style>");
            xml.Append("</Border>");
            xml.Append("<PaddingLeft>2pt</PaddingLeft>");
            xml.Append("<PaddingRight>2pt</PaddingRight>");
            xml.Append("<PaddingTop>2pt</PaddingTop>");
            xml.Append("<PaddingBottom>2pt</PaddingBottom>");
            xml.Append("</Style>");
            xml.Append("</Textbox>");

            return xml.ToString();
        }

        private string _getDataListTable()
        {
            var xml = new StringBuilder("<Tablix  xmlns=\"http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition\"");
            xml.Append(" xmlns:rd=\"http://schemas.microsoft.com/SQLServer/reporting/reportdesigner\" Name = \"TabDataList\">");
            var hw = 16.2204;
            var nw = 1.0;
            var c = DataSelected.Count;
            var aw = (hw - nw) / c;
            xml.Append("<TablixBody><TablixColumns>");
            xml.Append("<TablixColumn><Width>");
            xml.Append(nw);
            xml.Append("cm </Width></TablixColumn>");
            for (int i = 0; i < c; i++)
            {
                xml.Append("<TablixColumn><Width>");
                xml.Append(aw);
                xml.Append("cm </Width></TablixColumn>");
            }

            xml.Append("</TablixColumns>");
            xml.Append("<TablixRows><TablixRow><Height> 0.6cm </Height><TablixCells>");
            #region 表头
            xml.Append("<TablixCell>");
            xml.Append("<CellContents>");
            xml.Append("<Textbox Name = \"Textbox16\">");
            xml.Append("<CanGrow>true</CanGrow>");
            xml.Append("<KeepTogether>true</KeepTogether>");
            xml.Append("<Paragraphs>");
            xml.Append("<Paragraph>");
            xml.Append("<TextRuns>");
            xml.Append("<TextRun>");
            xml.Append("<Value >= First(Fields!Dln.Value, \"DN\") </Value>");
            xml.Append("<Style>");
            xml.Append("<FontFamily>宋体</FontFamily>");
            xml.Append("</Style>");
            xml.Append("</TextRun>");
            xml.Append("</TextRuns>");
            xml.Append("<Style/>");
            xml.Append("</Paragraph>");
            xml.Append("</Paragraphs>");
            xml.Append("<rd:DefaultName>Textbox16</rd:DefaultName>");
            xml.Append("<Style>");
            xml.Append("<Border>");
            xml.Append("<Style>None</Style>");
            xml.Append("</Border>");
            xml.Append("<PaddingLeft>2pt</PaddingLeft>");
            xml.Append("<PaddingRight>2pt</PaddingRight>");
            xml.Append("<PaddingTop>2pt</PaddingTop>");
            xml.Append("<PaddingBottom>2pt</PaddingBottom>");
            xml.Append("</Style>");
            xml.Append("</Textbox>");
            xml.Append("</CellContents>");
            xml.Append("</TablixCell>");
            for (int i = 1; i <= c; i++)
            {
                xml.Append("<TablixCell>");
                xml.Append("<CellContents>");
                xml.Append("<Textbox Name = \"TextDln");
                xml.Append(i);
                xml.Append("\">");
                xml.Append("<CanGrow>true</CanGrow>");
                xml.Append("<KeepTogether>true</KeepTogether>");
                xml.Append("<Paragraphs>");
                xml.Append("<Paragraph>");
                xml.Append("<TextRuns>");
                xml.Append("<TextRun>");
                xml.Append("<Value >= First(Fields!Dln");
                xml.Append(i);
                xml.Append(".Value, \"DN\") </Value>");
                xml.Append("<Style>");
                xml.Append("<FontFamily>宋体</FontFamily>");
                xml.Append("</Style>");
                xml.Append("</TextRun>");
                xml.Append("</TextRuns>");
                xml.Append("<Style/>");
                xml.Append("</Paragraph>");
                xml.Append("</Paragraphs>");
                xml.Append("<rd:DefaultName>TextDln");
                xml.Append(i);
                xml.Append("</rd:DefaultName>");
                xml.Append("<Style>");
                xml.Append("<Border>");
                xml.Append("<Style>None</Style>");
                xml.Append("</Border>");
                xml.Append("<PaddingLeft>2pt</PaddingLeft>");
                xml.Append("<PaddingRight>2pt</PaddingRight>");
                xml.Append("<PaddingTop>2pt</PaddingTop>");
                xml.Append("<PaddingBottom>2pt</PaddingBottom>");
                xml.Append("</Style>");
                xml.Append("</Textbox>");
                xml.Append("</CellContents>");
                xml.Append("</TablixCell>");
            }
            #endregion
            xml.Append("</TablixCells>");
            xml.Append("</TablixRow>");
            xml.Append("<TablixRow>");
            xml.Append("<Height>0.4cm</Height>");
            xml.Append("<TablixCells>");
            #region 表体
            xml.Append("<TablixCell>");
            xml.Append("<CellContents>");
            xml.Append("<Textbox Name = \"TextNo1\">");
            xml.Append("<CanGrow>true</CanGrow>");
            xml.Append("<KeepTogether>true</KeepTogether>");
            xml.Append("<Paragraphs>");
            xml.Append("<Paragraph>");
            xml.Append("<TextRuns>");
            xml.Append("<TextRun>");
            xml.Append("<Value>=RowNumber(nothing) </Value>");
            xml.Append("<Style>");
            xml.Append("<FontFamily>宋体</FontFamily>");
            xml.Append("</Style>");
            xml.Append("</TextRun>");
            xml.Append("</TextRuns>");
            xml.Append("<Style/>");
            xml.Append("</Paragraph>");
            xml.Append("</Paragraphs>");
            xml.Append("<rd:DefaultName>Textbox17</rd:DefaultName>");
            xml.Append("<Style>");
            xml.Append("<Border>");
            xml.Append("<Style>None</Style>");
            xml.Append("</Border>");
            xml.Append("<PaddingLeft>2pt</PaddingLeft>");
            xml.Append("<PaddingRight>2pt</PaddingRight>");
            xml.Append("<PaddingTop>2pt</PaddingTop>");
            xml.Append("<PaddingBottom>2pt</PaddingBottom>");
            xml.Append("</Style>");
            xml.Append("</Textbox>");
            xml.Append("</CellContents>");
            xml.Append("</TablixCell>");
            for (int i = 1; i <= c; i++)
            {
                xml.Append("<TablixCell>");
                xml.Append("<CellContents>");
                xml.Append("<Textbox Name = \"Data");
                xml.Append(i);
                xml.Append("\">");
                xml.Append("<CanGrow>true</CanGrow>");
                xml.Append("<KeepTogether>true</KeepTogether>");
                xml.Append("<Paragraphs>");
                xml.Append("<Paragraph>");
                xml.Append("<TextRuns>");
                xml.Append("<TextRun>");
                xml.Append("<Value>=Fields!Data");
                xml.Append(i);
                xml.Append(".Value</Value>");
                xml.Append("<Style>");
                xml.Append("<FontFamily>宋体</FontFamily>");
                xml.Append("</Style>");
                xml.Append("</TextRun>");
                xml.Append("</TextRuns>");
                xml.Append("<Style/>");
                xml.Append("</Paragraph>");
                xml.Append("</Paragraphs>");
                xml.Append("<rd:DefaultName>Data");
                xml.Append(i);
                xml.Append("</rd:DefaultName>");
                xml.Append("<Style>");
                xml.Append("<Border>");
                xml.Append("<Style>None</Style>");
                xml.Append("</Border>");
                xml.Append("<PaddingLeft>2pt</PaddingLeft>");
                xml.Append("<PaddingRight>2pt</PaddingRight>");
                xml.Append("<PaddingTop>2pt</PaddingTop>");
                xml.Append("<PaddingBottom>2pt</PaddingBottom>");
                xml.Append("</Style>");
                xml.Append("</Textbox>");
                xml.Append("</CellContents>");
                xml.Append("</TablixCell>");
            }
            #endregion
            xml.Append("</TablixCells>");
            xml.Append("</TablixRow>");
            xml.Append("</TablixRows>");
            xml.Append("</TablixBody>");
            xml.Append("<TablixColumnHierarchy>");
            xml.Append("<TablixMembers>");
            xml.Append("<TablixMember />");
            for (int i = 0; i < c; i++)
            {
                xml.Append("<TablixMember />");
            }

            xml.Append("</TablixMembers>");
            xml.Append("</TablixColumnHierarchy>");
            xml.Append("<TablixRowHierarchy>");
            xml.Append("<TablixMembers>");
            xml.Append("<TablixMember>");
            xml.Append("<KeepWithGroup>After</KeepWithGroup>");
            xml.Append("</TablixMember>");
            xml.Append("<TablixMember>");
            xml.Append("<Group Name=\"详细信息3\" />");
            xml.Append("</TablixMember>");
            xml.Append("</TablixMembers>");
            xml.Append("</TablixRowHierarchy>");
            xml.Append("<DataSetName>DL</DataSetName>");
            xml.Append("<Top>17.59072cm</Top>");
            xml.Append("<Left>0.1261cm</Left>");
            xml.Append("<Height>1.2cm</Height>");
            xml.Append("<Width>10cm</Width>");
            xml.Append("<ZIndex>7</ZIndex>");
            xml.Append("<Style>");
            xml.Append("<Border>");
            xml.Append("<Style>None</Style>");
            xml.Append("</Border>");
            xml.Append("</Style>");
            xml.Append("</Tablix>");
            return xml.ToString();
        }

        private string _getResultListTable()
        {
            var xml = new StringBuilder("<Tablix  xmlns=\"http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition\"");
            xml.Append(" xmlns:rd=\"http://schemas.microsoft.com/SQLServer/reporting/reportdesigner\" Name = \"TabResultList\">");
            var hw = 16.2204;
            var nw = 2.0;
            var c = ResultSelected.Count;
            var aw = (hw - nw) / c;
            xml.Append("<TablixBody><TablixColumns>");
            xml.Append("<TablixColumn><Width>");
            xml.Append(nw);
            xml.Append("cm </Width></TablixColumn>");
            for (int i = 0; i < c; i++)
            {
                xml.Append("<TablixColumn><Width>");
                xml.Append(aw);
                xml.Append("cm </Width></TablixColumn>");
            }
            xml.Append("</TablixColumns>");
            xml.Append("<TablixRows><TablixRow><Height> 0.4cm </Height><TablixCells>");
            #region 表头
            xml.Append("<TablixCell>");
            xml.Append("<CellContents>");
            xml.Append("<Textbox Name = \"Textbox161\">");
            xml.Append("<CanGrow>true</CanGrow>");
            xml.Append("<KeepTogether>true</KeepTogether>");
            xml.Append("<Paragraphs>");
            xml.Append("<Paragraph>");
            xml.Append("<TextRuns>");
            xml.Append("<TextRun>");
            xml.Append("<Value >= First(Fields!Dln.Value, \"RN\") </Value>");
            xml.Append("<Style>");
            xml.Append("<FontFamily>宋体</FontFamily>");
            xml.Append("</Style>");
            xml.Append("</TextRun>");
            xml.Append("</TextRuns>");
            xml.Append("<Style/>");
            xml.Append("</Paragraph>");
            xml.Append("</Paragraphs>");
            xml.Append("<rd:DefaultName>Textbox16</rd:DefaultName>");
            xml.Append("<Style>");
            xml.Append("<Border>");
            xml.Append("<Style>None</Style>");
            xml.Append("</Border>");
            xml.Append("<PaddingLeft>2pt</PaddingLeft>");
            xml.Append("<PaddingRight>2pt</PaddingRight>");
            xml.Append("<PaddingTop>2pt</PaddingTop>");
            xml.Append("<PaddingBottom>2pt</PaddingBottom>");
            xml.Append("</Style>");
            xml.Append("</Textbox>");
            xml.Append("</CellContents>");
            xml.Append("</TablixCell>");
            for (int i = 1; i <= c; i++)
            {
                xml.Append("<TablixCell>");
                xml.Append("<CellContents>");
                xml.Append("<Textbox Name = \"ResultDln");
                xml.Append(i);
                xml.Append("\">");
                xml.Append("<CanGrow>true</CanGrow>");
                xml.Append("<KeepTogether>true</KeepTogether>");
                xml.Append("<Paragraphs>");
                xml.Append("<Paragraph>");
                xml.Append("<TextRuns>");
                xml.Append("<TextRun>");
                xml.Append("<Value >= First(Fields!Dln");
                xml.Append(i);
                xml.Append(".Value, \"RN\") </Value>");
                xml.Append("<Style>");
                xml.Append("<FontFamily>宋体</FontFamily>");
                xml.Append("</Style>");
                xml.Append("</TextRun>");
                xml.Append("</TextRuns>");
                xml.Append("<Style/>");
                xml.Append("</Paragraph>");
                xml.Append("</Paragraphs>");
                xml.Append("<rd:DefaultName>ResultDln");
                xml.Append(i);
                xml.Append("</rd:DefaultName>");
                xml.Append("<Style>");
                xml.Append("<Border>");
                xml.Append("<Style>None</Style>");
                xml.Append("</Border>");
                xml.Append("<PaddingLeft>2pt</PaddingLeft>");
                xml.Append("<PaddingRight>2pt</PaddingRight>");
                xml.Append("<PaddingTop>2pt</PaddingTop>");
                xml.Append("<PaddingBottom>2pt</PaddingBottom>");
                xml.Append("</Style>");
                xml.Append("</Textbox>");
                xml.Append("</CellContents>");
                xml.Append("</TablixCell>");
            }
            #endregion
            xml.Append("</TablixCells>");
            xml.Append("</TablixRow>");
            xml.Append("<TablixRow>");
            xml.Append("<Height>0.4cm</Height>");
            xml.Append("<TablixCells>");
            #region 表体
            xml.Append("<TablixCell>");
            xml.Append("<CellContents>");
            xml.Append("<Textbox Name = \"TextNo\">");
            xml.Append("<CanGrow>true</CanGrow>");
            xml.Append("<KeepTogether>true</KeepTogether>");
            xml.Append("<Paragraphs>");
            xml.Append("<Paragraph>");
            xml.Append("<TextRuns>");
            xml.Append("<TextRun>");
            xml.Append("<Value>=Fields!Data.Value</Value>");
            xml.Append("<Style>");
            xml.Append("<FontFamily>宋体</FontFamily>");
            xml.Append("</Style>");
            xml.Append("</TextRun>");
            xml.Append("</TextRuns>");
            xml.Append("<Style/>");
            xml.Append("</Paragraph>");
            xml.Append("</Paragraphs>");
            xml.Append("<rd:DefaultName>Textbox17</rd:DefaultName>");
            xml.Append("<Style>");
            xml.Append("<Border>");
            xml.Append("<Style>None</Style>");
            xml.Append("</Border>");
            xml.Append("<PaddingLeft>2pt</PaddingLeft>");
            xml.Append("<PaddingRight>2pt</PaddingRight>");
            xml.Append("<PaddingTop>2pt</PaddingTop>");
            xml.Append("<PaddingBottom>2pt</PaddingBottom>");
            xml.Append("</Style>");
            xml.Append("</Textbox>");
            xml.Append("</CellContents>");
            xml.Append("</TablixCell>");
            for (int i = 1; i <= c; i++)
            {
                xml.Append("<TablixCell>");
                xml.Append("<CellContents>");
                xml.Append("<Textbox Name = \"Data1");
                xml.Append(i);
                xml.Append("\">");
                xml.Append("<CanGrow>true</CanGrow>");
                xml.Append("<KeepTogether>true</KeepTogether>");
                xml.Append("<Paragraphs>");
                xml.Append("<Paragraph>");
                xml.Append("<TextRuns>");
                xml.Append("<TextRun>");
                xml.Append("<Value>=Fields!Data");
                xml.Append(i);
                xml.Append(".Value</Value>");
                xml.Append("<Style>");
                xml.Append("<FontFamily>宋体</FontFamily>");
                xml.Append("</Style>");
                xml.Append("</TextRun>");
                xml.Append("</TextRuns>");
                xml.Append("<Style/>");
                xml.Append("</Paragraph>");
                xml.Append("</Paragraphs>");
                xml.Append("<rd:DefaultName>Data1");
                xml.Append(i);
                xml.Append("</rd:DefaultName>");
                xml.Append("<Style>");
                xml.Append("<Border>");
                xml.Append("<Style>None</Style>");
                xml.Append("</Border>");
                xml.Append("<PaddingLeft>2pt</PaddingLeft>");
                xml.Append("<PaddingRight>2pt</PaddingRight>");
                xml.Append("<PaddingTop>2pt</PaddingTop>");
                xml.Append("<PaddingBottom>2pt</PaddingBottom>");
                xml.Append("</Style>");
                xml.Append("</Textbox>");
                xml.Append("</CellContents>");
                xml.Append("</TablixCell>");
            }
            #endregion
            xml.Append("</TablixCells>");
            xml.Append("</TablixRow>");
            xml.Append("</TablixRows>");
            xml.Append("</TablixBody>");
            xml.Append("<TablixColumnHierarchy>");
            xml.Append("<TablixMembers>");
            xml.Append("<TablixMember />");
            for (int i = 0; i < c; i++)
            {
                xml.Append("<TablixMember />");
            }

            xml.Append("</TablixMembers>");
            xml.Append("</TablixColumnHierarchy>");
            xml.Append("<TablixRowHierarchy>");
            xml.Append("<TablixMembers>");
            xml.Append("<TablixMember>");
            xml.Append("<KeepWithGroup>After</KeepWithGroup>");
            xml.Append("</TablixMember>");
            xml.Append("<TablixMember>");
            xml.Append("<Group Name=\"详细信息4\" />");
            xml.Append("</TablixMember>");
            xml.Append("</TablixMembers>");
            xml.Append("</TablixRowHierarchy>");
            xml.Append("<DataSetName>RL</DataSetName>");
            xml.Append("<Top>2.775cm</Top>");
            xml.Append("<Left>0.11305cm</Left>");
            xml.Append("<Height>1.2cm</Height>");
            xml.Append("<Width>16.2204cm</Width>");
            xml.Append("<ZIndex>7</ZIndex>");
            xml.Append("<Style>");
            xml.Append("<Border>");
            xml.Append("<Style>None</Style>");
            xml.Append("</Border>");
            xml.Append("</Style>");
            xml.Append("</Tablix>");
            return xml.ToString();
        }
    }
}
